{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "kaggle-whales.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "collapsed_sections": [
        "buv7F_ZavIdv"
      ],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/gdoteof/neuralnet_stuff/blob/master/kaggle_whales.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "metadata": {
        "id": "1O5XN1t5cpsG",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "#Install fast.ai dependencies.  \n",
        "\n",
        "Here you want to make sure you have the gpu runtime selected.\n",
        "\n",
        "![alt text](https://i.imgur.com/tCvtjwC.png)\n",
        "\n",
        "The below will download and run a script to install fast.ai dependencies."
      ]
    },
    {
      "metadata": {
        "id": "mRNbgbD5a4dD",
        "colab_type": "code",
        "outputId": "b05b10b7-6ae0-4b27-d1ed-5220516bcfc4",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1577
        }
      },
      "cell_type": "code",
      "source": [
        "  !curl https://raw.githubusercontent.com/fastai/course-v3/master/docs/setup/colab | bash"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n",
            "                                 Dload  Upload   Total   Spent    Left  Speed\n",
            "100   665  100   665    0     0   1763      0 --:--:-- --:--:-- --:--:--  1759\n",
            "Collecting pillow==4.1.1\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/36/e5/88b3d60924a3f8476fa74ec086f5fbaba56dd6cee0d82845f883b6b6dd18/Pillow-4.1.1-cp36-cp36m-manylinux1_x86_64.whl (5.7MB)\n",
            "\u001b[K    100% |████████████████████████████████| 5.7MB 6.5MB/s \n",
            "\u001b[?25hRequirement already satisfied, skipping upgrade: olefile in /usr/local/lib/python3.6/dist-packages (from pillow==4.1.1) (0.46)\n",
            "Installing collected packages: pillow\n",
            "  Found existing installation: Pillow 4.0.0\n",
            "    Uninstalling Pillow-4.0.0:\n",
            "      Successfully uninstalled Pillow-4.0.0\n",
            "Successfully installed pillow-4.1.1\n",
            "Looking in links: https://download.pytorch.org/whl/nightly/cu92/torch_nightly.html\n",
            "Collecting torch_nightly\n",
            "\u001b[?25l  Downloading https://download.pytorch.org/whl/nightly/cu92/torch_nightly-1.0.0.dev20181206-cp36-cp36m-linux_x86_64.whl (576.2MB)\n",
            "\u001b[K    100% |████████████████████████████████| 576.2MB 27kB/s \n",
            "tcmalloc: large alloc 1073750016 bytes == 0x62472000 @  0x7f8bf99702a4 0x591a07 0x5b5d56 0x502e9a 0x506859 0x502209 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x507641 0x502209 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x507641 0x504c28 0x502540 0x502f3d 0x507641\n",
            "\u001b[?25hInstalling collected packages: torch-nightly\n",
            "Successfully installed torch-nightly-1.0.0.dev20181206\n",
            "Cloning into 'course-v3'...\n",
            "remote: Enumerating objects: 2809, done.\u001b[K\n",
            "remote: Total 2809 (delta 0), reused 0 (delta 0), pack-reused 2809\u001b[K\n",
            "Receiving objects: 100% (2809/2809), 105.10 MiB | 10.38 MiB/s, done.\n",
            "Resolving deltas: 100% (1539/1539), done.\n",
            "Collecting fastai\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/f5/17/b5ab3f9a44b45661d9eb6e29001fe39c39ebb287ce9a9f1670d07bda0d4d/fastai-1.0.39-py3-none-any.whl (150kB)\n",
            "\u001b[K    100% |████████████████████████████████| 153kB 6.8MB/s \n",
            "\u001b[?25hCollecting torch (from fastai)\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/7e/60/66415660aa46b23b5e1b72bc762e816736ce8d7260213e22365af51e8f9c/torch-1.0.0-cp36-cp36m-manylinux1_x86_64.whl (591.8MB)\n",
            "\u001b[K    100% |████████████████████████████████| 591.8MB 28kB/s \n",
            "tcmalloc: large alloc 1073750016 bytes == 0x62382000 @  0x7f709665e2a4 0x591a07 0x5b5d56 0x502e9a 0x506859 0x502209 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x507641 0x502209 0x502f3d 0x506859 0x504c28 0x502540 0x502f3d 0x507641 0x504c28 0x502540 0x502f3d 0x507641\n",
            "\u001b[?25hCollecting fastprogress>=0.1.18 (from fastai)\n",
            "  Downloading https://files.pythonhosted.org/packages/78/57/24a5e20f4a357f7f1c90dd5250071951c832b2480fd4fefd7be48edf4180/fastprogress-0.1.18-py3-none-any.whl\n",
            "Requirement already satisfied, skipping upgrade: pyyaml in /usr/local/lib/python3.6/dist-packages (from fastai) (3.13)\n",
            "Collecting typing (from fastai)\n",
            "  Downloading https://files.pythonhosted.org/packages/4a/bd/eee1157fc2d8514970b345d69cb9975dcd1e42cd7e61146ed841f6e68309/typing-3.6.6-py3-none-any.whl\n",
            "Requirement already satisfied, skipping upgrade: pandas in /usr/local/lib/python3.6/dist-packages (from fastai) (0.22.0)\n",
            "Requirement already satisfied, skipping upgrade: requests in /usr/local/lib/python3.6/dist-packages (from fastai) (2.18.4)\n",
            "Collecting bottleneck (from fastai)\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/05/ae/cedf5323f398ab4e4ff92d6c431a3e1c6a186f9b41ab3e8258dff786a290/Bottleneck-1.2.1.tar.gz (105kB)\n",
            "\u001b[K    100% |████████████████████████████████| 112kB 32.2MB/s \n",
            "\u001b[?25hRequirement already satisfied, skipping upgrade: matplotlib in /usr/local/lib/python3.6/dist-packages (from fastai) (2.1.2)\n",
            "Collecting nvidia-ml-py3 (from fastai)\n",
            "  Downloading https://files.pythonhosted.org/packages/6d/64/cce82bddb80c0b0f5c703bbdafa94bfb69a1c5ad7a79cff00b482468f0d3/nvidia-ml-py3-7.352.0.tar.gz\n",
            "Requirement already satisfied, skipping upgrade: numexpr in /usr/local/lib/python3.6/dist-packages (from fastai) (2.6.9)\n",
            "Requirement already satisfied, skipping upgrade: scipy in /usr/local/lib/python3.6/dist-packages (from fastai) (1.1.0)\n",
            "Requirement already satisfied, skipping upgrade: numpy>=1.12 in /usr/local/lib/python3.6/dist-packages (from fastai) (1.14.6)\n",
            "Requirement already satisfied, skipping upgrade: Pillow in /usr/local/lib/python3.6/dist-packages (from fastai) (4.1.1)\n",
            "Requirement already satisfied, skipping upgrade: packaging in /usr/local/lib/python3.6/dist-packages (from fastai) (18.0)\n",
            "Requirement already satisfied, skipping upgrade: spacy>=2.0.18 in /usr/local/lib/python3.6/dist-packages (from fastai) (2.0.18)\n",
            "Collecting torchvision (from fastai)\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/ca/0d/f00b2885711e08bd71242ebe7b96561e6f6d01fdb4b9dcf4d37e2e13c5e1/torchvision-0.2.1-py2.py3-none-any.whl (54kB)\n",
            "\u001b[K    100% |████████████████████████████████| 61kB 27.5MB/s \n",
            "\u001b[?25hCollecting dataclasses; python_version < \"3.7\" (from fastai)\n",
            "  Downloading https://files.pythonhosted.org/packages/26/2f/1095cdc2868052dd1e64520f7c0d5c8c550ad297e944e641dbf1ffbb9a5d/dataclasses-0.6-py3-none-any.whl\n",
            "Requirement already satisfied, skipping upgrade: python-dateutil>=2 in /usr/local/lib/python3.6/dist-packages (from pandas->fastai) (2.5.3)\n",
            "Requirement already satisfied, skipping upgrade: pytz>=2011k in /usr/local/lib/python3.6/dist-packages (from pandas->fastai) (2018.9)\n",
            "Requirement already satisfied, skipping upgrade: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (3.0.4)\n",
            "Requirement already satisfied, skipping upgrade: urllib3<1.23,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (1.22)\n",
            "Requirement already satisfied, skipping upgrade: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (2018.11.29)\n",
            "Requirement already satisfied, skipping upgrade: idna<2.7,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->fastai) (2.6)\n",
            "Requirement already satisfied, skipping upgrade: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->fastai) (2.3.0)\n",
            "Requirement already satisfied, skipping upgrade: six>=1.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->fastai) (1.11.0)\n",
            "Requirement already satisfied, skipping upgrade: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->fastai) (0.10.0)\n",
            "Requirement already satisfied, skipping upgrade: olefile in /usr/local/lib/python3.6/dist-packages (from Pillow->fastai) (0.46)\n",
            "Requirement already satisfied, skipping upgrade: cymem<2.1.0,>=2.0.2 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (2.0.2)\n",
            "Requirement already satisfied, skipping upgrade: dill<0.3,>=0.2 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (0.2.8.2)\n",
            "Requirement already satisfied, skipping upgrade: plac<1.0.0,>=0.9.6 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (0.9.6)\n",
            "Requirement already satisfied, skipping upgrade: regex==2018.01.10 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (2018.1.10)\n",
            "Requirement already satisfied, skipping upgrade: preshed<2.1.0,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (2.0.1)\n",
            "Requirement already satisfied, skipping upgrade: ujson>=1.35 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (1.35)\n",
            "Requirement already satisfied, skipping upgrade: murmurhash<1.1.0,>=0.28.0 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (1.0.1)\n",
            "Requirement already satisfied, skipping upgrade: thinc<6.13.0,>=6.12.1 in /usr/local/lib/python3.6/dist-packages (from spacy>=2.0.18->fastai) (6.12.1)\n",
            "Requirement already satisfied, skipping upgrade: tqdm<5.0.0,>=4.10.0 in /usr/local/lib/python3.6/dist-packages (from thinc<6.13.0,>=6.12.1->spacy>=2.0.18->fastai) (4.28.1)\n",
            "Requirement already satisfied, skipping upgrade: msgpack<0.6.0,>=0.5.6 in /usr/local/lib/python3.6/dist-packages (from thinc<6.13.0,>=6.12.1->spacy>=2.0.18->fastai) (0.5.6)\n",
            "Requirement already satisfied, skipping upgrade: msgpack-numpy<0.4.4 in /usr/local/lib/python3.6/dist-packages (from thinc<6.13.0,>=6.12.1->spacy>=2.0.18->fastai) (0.4.3.2)\n",
            "Requirement already satisfied, skipping upgrade: cytoolz<0.10,>=0.9.0 in /usr/local/lib/python3.6/dist-packages (from thinc<6.13.0,>=6.12.1->spacy>=2.0.18->fastai) (0.9.0.1)\n",
            "Requirement already satisfied, skipping upgrade: wrapt<1.11.0,>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from thinc<6.13.0,>=6.12.1->spacy>=2.0.18->fastai) (1.10.11)\n",
            "Requirement already satisfied, skipping upgrade: toolz>=0.8.0 in /usr/local/lib/python3.6/dist-packages (from cytoolz<0.10,>=0.9.0->thinc<6.13.0,>=6.12.1->spacy>=2.0.18->fastai) (0.9.0)\n",
            "Building wheels for collected packages: bottleneck, nvidia-ml-py3\n",
            "  Running setup.py bdist_wheel for bottleneck ... \u001b[?25l-\b \b\\\b \b|\b \b/\b \b-\b \b\\\b \b|\b \b/\b \bdone\n",
            "\u001b[?25h  Stored in directory: /root/.cache/pip/wheels/f2/bf/ec/e0f39aa27001525ad455139ee57ec7d0776fe074dfd78c97e4\n",
            "  Running setup.py bdist_wheel for nvidia-ml-py3 ... \u001b[?25l-\b \bdone\n",
            "\u001b[?25h  Stored in directory: /root/.cache/pip/wheels/e4/1d/06/640c93f5270d67d0247f30be91f232700d19023f9e66d735c7\n",
            "Successfully built bottleneck nvidia-ml-py3\n",
            "Installing collected packages: torch, fastprogress, typing, bottleneck, nvidia-ml-py3, torchvision, dataclasses, fastai\n",
            "Successfully installed bottleneck-1.2.1 dataclasses-0.6 fastai-1.0.39 fastprogress-0.1.18 nvidia-ml-py3-7.352.0 torch-1.0.0 torchvision-0.2.1 typing-3.6.6\n",
            "Already up to date.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "metadata": {
        "id": "CeYFBacCbHNz",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "import sys\n",
        "from fastai import *\n",
        "from fastai.vision import *"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "_EeMKWr6d1x2",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "###Check GPU\n",
        "\n",
        "The following should output:\n",
        "\n",
        "\n",
        "```\n",
        "1.0.0\n",
        "True\n",
        "True```\n",
        "\n"
      ]
    },
    {
      "metadata": {
        "id": "qlq42S8HcdH7",
        "colab_type": "code",
        "outputId": "f87cc176-7a2c-4094-dede-2eff34dc05f0",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 69
        }
      },
      "cell_type": "code",
      "source": [
        "\n",
        "print(torch.__version__)\n",
        "print(torch.cuda.is_available())\n",
        "print(torch.backends.cudnn.enabled)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1.0.0\n",
            "True\n",
            "True\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "metadata": {
        "id": "XniXyMb_eHfl",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "###(Optional) Connect Google Drive"
      ]
    },
    {
      "metadata": {
        "id": "Kq0gbJ90fE7a",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "Go the the URL, give permissions on your google account, and copy the code in the box that is presented when you run the following code."
      ]
    },
    {
      "metadata": {
        "id": "pgVcCN3ocgdz",
        "colab_type": "code",
        "outputId": "140f5d56-259d-46bc-9917-234f306b42bc",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 124
        }
      },
      "cell_type": "code",
      "source": [
        "from google.colab import drive\n",
        "drive.mount('/content/drive', force_remount=True)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdocs.test%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.photos.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fpeopleapi.readonly&response_type=code\n",
            "\n",
            "Enter your authorization code:\n",
            "··········\n",
            "Mounted at /content/drive\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "metadata": {
        "id": "SIi5_e0bq34I",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "BASE = \"/content/drive/My Drive/ai/whales\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "buv7F_ZavIdv",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "## The rest below on needs to be run once."
      ]
    },
    {
      "metadata": {
        "id": "9x93aHqofgc3",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "###Download data from Kaggle"
      ]
    },
    {
      "metadata": {
        "id": "qIywkRzNqHcb",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "Generate an API Token from Kaggle.  They will give you a file called kaggle.json.  Inside that file there are two values you need to fill in for `KAGGLE_USERNAME` and `KAGGLE_KEY`"
      ]
    },
    {
      "metadata": {
        "id": "IGVo4knrm6mF",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "!KAGGLE_USERNAME=gdoteof KAGGLE_KEY=1xxxxxxxxxxxxxxxxxxxxxxxxxx2 kaggle competitions download -c humpback-whale-identification\n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "S516PntYqh7K",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "###Alright, now let's move it all to our google drive.  "
      ]
    },
    {
      "metadata": {
        "id": "D80DTvYbm98f",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "!mkdir -p \"{BASE}/train\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "tVXLlFl4qwLT",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "!mv test.zip train.zip train.csv \"{BASE}\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "gDuwuJCsrA4Y",
        "colab_type": "code",
        "outputId": "35cbef16-6ff7-42dc-82ec-d71502bf6534",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "cell_type": "code",
      "source": [
        "!echo {BASE}"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "/content/drive/My Drive/ai/whales\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "metadata": {
        "id": "boKzrgswrH9i",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "!unzip \"{BASE}\"/train.zip -d \"{BASE}/train\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "3eHEI_XgtfHF",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "!mkdir -p \"{BASE}/test\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "msJMG9WLtnPi",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "!unzip \"{BASE}\"/test.zip -d \"{BASE}/test\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "87E0fYyCuJtM",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "##Build our databunch!"
      ]
    },
    {
      "metadata": {
        "id": "tvBTpoEZuQD7",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "First we set up some meta-parameters (size of the input image to the net and the batch size)"
      ]
    },
    {
      "metadata": {
        "id": "5TOz8fRdlWQQ",
        "colab_type": "code",
        "outputId": "6c630938-a466-48c7-c9c8-9fc053dab65a",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "cell_type": "code",
      "source": [
        "!ls \"{BASE}\""
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "export.pkl  models  test  test.zip  train  train.csv  train.zip\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "metadata": {
        "id": "sLrhomNmMxqt",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "#ws means \"with separation\".  \n",
        "#we are running into an issue where there are classes in the validation set but not training.\n",
        "#this was going unnoticed before, but checks later are catching it\n",
        "from fastai.torch_core import *\n",
        "from fastai.basic_data import *\n",
        "from fastai.data_block import *\n",
        "from sklearn.model_selection import train_test_split\n",
        "\n",
        "\n",
        "def create_from_ll(lls:LabelLists, bs:int=64, ds_tfms:Optional[TfmList]=None,\n",
        "            num_workers:int=defaults.cpus, tfms:Optional[Collection[Callable]]=None, device:torch.device=None,\n",
        "            test:Optional[PathOrStr]=None, collate_fn:Callable=data_collate, size:int=None, no_check:bool=False, **kwargs)->'ImageDataBunch':\n",
        "    \"Create an `ImageDataBunch` from `LabelLists` `lls` with potential `ds_tfms`.\"\n",
        "    lls = lls.transform(tfms=ds_tfms, size=size, **kwargs)\n",
        "    if test is not None: lls.add_test_folder(test)\n",
        "    return lls.databunch(bs=bs, tfms=tfms, num_workers=num_workers, collate_fn=collate_fn, device=device, no_check=no_check)\n",
        "\n",
        " \n",
        "  \n",
        "def from_df_ws(path:PathOrStr, df:pd.DataFrame, folder:PathOrStr='.', sep=None, valid_pct:float=0.2,\n",
        "                fn_col:IntsOrStrs=0, label_col:IntsOrStrs=1, suffix:str='',\n",
        "                **kwargs:Any)->'ImageDataBunch':\n",
        "  \"Create from a `DataFrame` `df`.\"\n",
        "\n",
        "  \"Split the data set\"\n",
        "  df_train, df_valid = train_test_split(df, test_size=valid_pct, random_state=420)\n",
        "  \n",
        "  \"find all the stuff in valid thats not in train\"\n",
        "  df_diff  = df_valid[~df_valid[\"Id\"].isin(df_train[\"Id\"])]\n",
        "  \n",
        "  \"take that stuff out of valid\"\n",
        "  df_valid = df_valid[~df_valid[\"Id\"].isin(df_diff[\"Id\"])]\n",
        "\n",
        "  train_iil = ImageItemList.from_df(df_train, path=path, folder=folder, suffix=suffix, cols=fn_col)\n",
        "  valid_iil = ImageItemList.from_df(df_valid, path=path, folder=folder, suffix=suffix, cols=fn_col)\n",
        "\n",
        "  src = (ItemLists(path, train_iil, valid_iil)\n",
        "            .label_from_df(sep=sep, cols=label_col)) \n",
        "\n",
        "  return ImageDataBunch.create_from_ll(src, **kwargs)\n",
        "\n",
        "\n",
        "def from_csv_ws(path:PathOrStr, folder:PathOrStr='.', sep=None, csv_labels:PathOrStr='labels.csv', valid_pct:float=0.2,\n",
        "            fn_col:int=0, label_col:int=1, suffix:str='',\n",
        "            header:Optional[Union[int,str]]='infer', **kwargs:Any)->'ImageDataBunch':\n",
        "        \"Create from a csv file in `path/csv_labels`.\"\n",
        "        path = Path(path)\n",
        "        df = pd.read_csv(path/csv_labels, header=header)\n",
        "        return from_df_ws(path, df, folder=folder, sep=sep, valid_pct=valid_pct,\n",
        "                fn_col=fn_col, label_col=label_col, suffix=suffix, **kwargs)\n",
        "      \n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "aezKwFK9uXsu",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "sz=128\n",
        "bs=512  #6.2gb usage\n",
        "bs=768\n",
        "tfms = get_transforms(max_rotate=20, max_zoom=1.3, max_lighting=0.4, max_warp=0.4, p_affine=1., p_lighting=1.)\n",
        "data = from_csv_ws(path=BASE, folder=f'train', csv_labels=\"train.csv\", ds_tfms=tfms, bs=bs, size=sz)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "w7qt5Y144GCA",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 139
        },
        "outputId": "632a2c59-b081-41a3-e5d9-3bf709712540"
      },
      "cell_type": "code",
      "source": [
        "data.train_ds"
      ],
      "execution_count": 24,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "LabelList\n",
              "y: CategoryList (20288 items)\n",
              "[Category w_f497e3f, Category w_2db0644, Category new_whale, Category w_fd3e556, Category new_whale]...\n",
              "Path: /content/drive/My Drive/ai/whales\n",
              "x: ImageItemList (20288 items)\n",
              "[Image (3, 690, 1050), Image (3, 700, 1050), Image (3, 600, 1050), Image (3, 430, 752), Image (3, 424, 1050)]...\n",
              "Path: /content/drive/My Drive/ai/whales"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 24
        }
      ]
    },
    {
      "metadata": {
        "id": "qfhCormkuvXH",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "learn = create_cnn(data, models.resnet34, metrics=error_rate)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "dUokfsmjdJ1e",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        ""
      ]
    },
    {
      "metadata": {
        "id": "GUebn6lV3RXl",
        "colab_type": "code",
        "outputId": "5a68e0d1-53bb-4232-9ad1-c134595fc919",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 170
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_find()"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "    <div>\n",
              "        <style>\n",
              "            /* Turns off some styling */\n",
              "            progress {\n",
              "                /* gets rid of default border in Firefox and Opera. */\n",
              "                border: none;\n",
              "                /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
              "                background-size: auto;\n",
              "            }\n",
              "            .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
              "                background: #F44336;\n",
              "            }\n",
              "        </style>\n",
              "      <progress value='3' class='' max='4', style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
              "      75.00% [3/4 1:20:11<26:43]\n",
              "    </div>\n",
              "    \n",
              "<table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>9.065716</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>9.028165</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>3</th>\n",
              "    <th>8.272099</th>\n",
              "  </tr>\n",
              "</table>\n",
              "\n",
              "\n",
              "    <div>\n",
              "        <style>\n",
              "            /* Turns off some styling */\n",
              "            progress {\n",
              "                /* gets rid of default border in Firefox and Opera. */\n",
              "                border: none;\n",
              "                /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
              "                background-size: auto;\n",
              "            }\n",
              "            .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
              "                background: #F44336;\n",
              "            }\n",
              "        </style>\n",
              "      <progress value='0' class='progress-bar-interrupted' max='26', style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
              "      Interrupted\n",
              "    </div>\n",
              "    "
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "metadata": {
        "id": "WBGp75kcZLQs",
        "colab_type": "code",
        "outputId": "80621812-c666-4181-c436-bd812af070f5",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 361
        }
      },
      "cell_type": "code",
      "source": [
        "learn.recorder.plot()"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n83mh6EHAQv1CDMM447GePXtyzz33MGnSJAoKCrj11ltZv369b0fgbMrKagJZZqtkZibhcFSFuoyQ\nUg/UA1APQD2A6O/B6doGauoaSU20n3M7A9mD8+0sBHX1e3x8PHV1TYsLiouLW0zNA2RnZ3P99ddj\nMpno3r07GRkZFBcXB7NEERGR83JWeFe+h9ciOQhyqI8ZM4Z169YBsH79esaNG9fi52vXrmXFihUA\nOBwOSktLyc7ODmaJIiIi5+Us9658D69FchDA6fddu3axePFiCgsLsVqtrFu3jiVLlvDwww+zZs0a\ncnJyuPHGGwGYM2cOixYtYuLEiTzwwANs2LCBhoYG5s+ff96pdxERkWDzrXwPs9PZIIChPmjQIFau\nXHnG488999wZjz399NO+r5999tlAlSQiItJuJb5QD7+Ruq4oJyIichEcCnUREZHo4CivJSXBhj0m\n9KdTf5NCXUREpJUa3R5KK+rDcpQOCnUREZFWO1VVj8cwFOoiIiKRLpxXvoNCXUREpNUcZeG7SA4U\n6iIiIq3mHalnpSrURUREIlo4n84GCnUREZFWKymvxWY1k5IQnlc7VaiLiIi0gmEYOMpryewUh8lk\nCnU5Z6VQFxERaYXqukZq691hO/UOCnUREZFW8R5PzwjT09lAoS4iItIqvpXvGqmLiIhEtnBf+Q4K\ndRERkVYpCfMLz4BCXUREpFXC/RKxoFAXERFpFUd5HalJdmKs4XfLVS+FuoiIyAU0uj2cqqojMyV8\nR+mgUBcREbmg0oo6DCO8j6eDQl1EROSCfMfTw/RGLl4KdRERkQsoiYDT2UChLiIickGRcI46KNRF\nREQuyFFeB4T31eRAoS4iInJBJWW12GMsJMXHhLqU82pVqO/atYv33nsPgKeffprZs2ezZcuWgBYm\nIiISDgzDwFFRS2an2LC95apXq0J94cKF9OrViy1btrBz504effRRli5dGujaREREQq6qtoF6V3jf\nctWrVaFut9vp2bMnGzZsYOrUqfTt2xezWTP3IiIS/RwRcM13r1Ylc21tLW+//TbvvvsuV155JeXl\n5VRWVga6NhERkZCLlJXv0MpQ/8UvfsEbb7zBnDlzSExMZOXKldx2220BLk1ERCT0fPdRD/MLzwBY\nW/OkUaNGMWjQIBITE3E6nYwePZphw4YFujYREZGQi5QLz0ArR+oLFizg7bffpry8nOnTp7Nq1Srm\nz59/wdfl5+eTl5fHqlWrACgqKmLWrFnMmDGD++67D5fLdcZrfve73zFt2jSmT5/Ojh07Lm5rRERE\n/MxRXocJSE8O75u5QCtDfc+ePdx88828/fbb3HTTTfzhD3/g6NGj531NTU0NCxYsYPTo0b7Hli5d\nyowZM1i9ejU9evTg1VdfbfGazZs3c/ToUdasWcNjjz3GY4891oZNEhER8R9HeS1pyXZirOG/QLxV\nFRqGAcD777/PxIkTAc46yv46m83G8uXLycrK8j22adMmrrnmGgCuvvpqNm7c2OI1GzduJC8vD4A+\nffpQUVHB6dOnW7kpIiIi/tXQ6Ka8qj4ipt6hlcfUe/XqxfXXX09aWhoDBgzg9ddfJyUl5fy/2GrF\nam3562tra7HZbACkp6fjcDha/NzpdJKbm+v7Pi0tDYfDQWJi4jnfJzU1HmsY3LA+MzMp1CWEnHqg\nHoB6AOoBRE8PCoqrMIBLOidf9DaFogetCvWFCxeSn59Pnz59AOjbty9PPPFEu97YO/pv73PKymra\nVYc/ZGYm4XBUhbqMkFIP1ANQD0A9gOjqQf5hJwBJsdaL2qZA9uB8OwutCvW6ujr+/e9/88c//hGT\nycTQoUPp27fvRRcSHx9PXV0dsbGxFBcXt5iaB8jKysLpdPq+LykpITMz86LfR0RExB9KIujCM9DK\nY+qPPvoop0+fZvr06UydOhWn08kjjzxy0W82ZswY1q1bB8D69esZN25ci5+PHTvW9/Pdu3eTlZV1\n3ql3ERGRQPLenS2jU/ivfIdWjtSdTidPPfWU7/urr76aWbNmnfc1u3btYvHixRQWFmK1Wlm3bh1L\nlizh4YcfZs2aNeTk5HDjjTcCMGfOHBYtWsSwYcPIzc1l+vTpmEwm5s2b145NExERaR9nRWSN1FsV\n6rW1tdTW1hIX17RRNTU11NfXn/c1gwYNYuXKlWc8/txzz53x2NNPP+37+oEHHmhNSSIiIgFXWlGH\nLcZMUlx433LVq1WhPm3aNCZNmsSgQYOApqnx++67L6CFiYiIhJqzoo6MlLiwv+WqV6tCfcqUKYwd\nO5bdu3djMpl49NFHzzoKFxERiRY1dQ3U1DfSt9v5T+EOJ60KdYAuXbrQpUsX3/e6hKuIiEQzZ0XT\nIrn0lMhYJAetXP1+Nq05h1xERCRSeUM9oyOEeqQcXxAREWmLr0I9Mla+wwWm3ydMmHDW8DYMg7Ky\nsoAVJSIiEmre09kiaaR+3lBfvXp1sOoQEREJK6UROP1+3lDv2rVrsOoQEREJK86KOuwxFhIj5Bx1\naMcxdRERkWjWdI56bEStIVOoi4iIfENNXQO19Y0RdTobKNRFRETO4LuRi0JdREQkskXi6WygUBcR\nETlDaQSezgYKdRERkTP4RuoRch91L4W6iIjIN2j6XUREJEo4K+qw2ywkxLb6vmdhQaEuIiLyNYZh\nUFpZG3HnqINCXUREpIWa+kZq691kJEfW8XRQqIuIiLTgLI/M4+mgUBcREWnBd3e2CFv5Dgp1ERGR\nFpwReHc2L4W6iIjI10Tq6WygUBcREWnBex/1SLuZCyjURUREWnBW1BIbgeeog0JdRETExzCMiLyP\nupdCXUREpFl1XSN1LndEHk8HhbqIiIiP93S2SDyeDgp1ERERH++FZzIV6iIiIpHN6Vv5rul3ERGR\niFYawReeAQjqen2Px8O8efM4cOAAMTExzJ8/nz59+vh+PnHiRDp37ozFYgFgyZIlZGdnB7NEERHp\nwCL5ErEQ5FDfsGEDVVVVvPLKKxw7dozHHnuMZcuWtXjO8uXLSUhICGZZIiIiADgr64izW4i3R945\n6hDk6fcjR44wZMgQALp3786JEydwu93BLEFEROSsvOeopyfHReQ56hDkkfqll17KCy+8wOzZszl6\n9CgFBQWUlZWRkZHhe868efMoLCxk+PDhzJ0794KNTU2Nx2q1BLr0C8rMTAp1CSGnHqgHoB6AegCR\n2YOK0/XUu9x0zUr0S/2h6EFQQ33ChAls27aNH/3oR/Tv35/evXtjGIbv5/feey/jxo0jJSWFu+++\nm3Xr1nHddded93eWldUEuuwLysxMwuGoCnUZIaUeqAegHoB6AJHbg8NFlQAkxVnbXX8ge3C+nYWg\nHzSYM2eO7+u8vDzS09N93994442+r8ePH09+fv4FQ11ERMQfSiP47mxeQT2mvm/fPn75y18C8OGH\nHzJw4EDM5qYSqqqquP3223G5XAB89tln9OvXL5jliYhIBxbJ91H3CvoxdcMwmDJlCna7nSVLlvDa\na6+RlJTEtddey/jx45k2bRp2u52BAwdqlC4iIkHjO51Nod46ZrOZxx9/vMVjkydP9n09e/ZsZs+e\nHcySREREAHCUR/5IXVeUExGRDq/e5WZ/QRlZneKIj40JdTltplAXEZEOb/tBB64GDyMHRvZVTBXq\n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\n9vQgGpxt+89l1KhRvP/++7hcLoqLiykpKaFv376MHTuWd955B/Bff3SXtrPYtWsXixcvprCwEKvV\nSnZ2Nvfffz9PPvkkZrMZu93Ok08+SadOnVq8rqSkhIceeoj6+npycnJYtGgRMTExfPHFFyxcuBCT\nycS4ceN8e2/hzN89+P3vf8+nn36K2Wxm4sSJEbFYzN898Nq0aRP//Oc/efzxx4O9SRfN3z1YtmwZ\n7777LoZhcNVVV3HPPfeEaMtaz589OH78ODfeeCNDhgzxPe+2227zLSYLV/7sgdls5rbbbqOyspLi\n4mL69evHz372szavLA+Gtm7/161cuZI33ngDk8nE/fffz+jRo6murua///u/KS8vJzk5md///vck\nJSW1q1aFuoiISJTQ9LuIiEiUUKiLiIhECYW6iIhIlFCoi4iIRAmFuoiISJRQqItEkOPHjzN+/Pig\nvqe/7qrXv39/Zs6c6btT39SpU1m/fv0FX/fGG2/g8Xja/f4iHYGuKCci57Vy5Uq//a7nn38eq7Xp\nnx2n08kPfvADRo4ced7ze//0pz8xadIkzGaNQUQuRKEuEiXeeustVq1ahWEYpKWlsXDhQlJTU1m9\nejX/+te/iImJwW638/TTT5OcnMzEiROZNGkSBQUFPPjgg9x1111ceeWV7Nixg+rqapYtW0Z2djb9\n+/dn9+7dPPPMM5SXl3Py5EmOHj3Kt7/9bR599FHq6+t56KGHKCwspHPnzlgsFsaOHcvNN9983noz\nMjLIzMzk2LFjJCcnM2/ePA4dOoTL5eLyyy/nkUceYenSpRw9epTbbruNP//5z+zbt4+//OUvGIaB\n1WplwYIFEXmZWZFA0a6vSBQoKiri2Wef5fnnn+fll19m5MiRLFu2DID6+npWrFjBqlWr6Nq1K2vX\nrvW9rmfPnr7boX755ZdMnjyZl156iQEDBvD222+f8T579uxh6dKlvPrqq7z22mtUVFSwdu1aGhsb\n+cc//sFvfvMbPv7441bVvGvXLkpKSujTpw8VFRX079+fl156iX/84x989NFH5Ofnc++99wJNI3y7\n3c68efP405/+xKpVq5g5cyZPPPFEe1snElU0UheJAtu3b8fhcHD77bcDTXeN6tatGwCdOnXiJz/5\nCWazmcLCQjIzM32vu+KKK3xfp6am+q7Jn5OTc9b7fA8fPhyLxYLFYiE1NZWKigr27t3LyJEjAcjM\nzDzvfbJvu+02TCYTTqeT2NhYnn32WRISEoiNjaWoqIhp06Zhs9lwOByUlZW1eO2BAwdwOBy+yyy7\n3e4zbqYh0tEp1EWigM1mY8iQIb7RudfJkydZvHgxb775Junp6SxevLjFz79+TXqLxdLiZ2e7gvTZ\nnuPxeFoc7z7fsW/vMfUdO3bw0EMPcemllwJNN8TYuXMnL730ElarlcmTJ591G3Nycvx6jF8k2mj6\nXSQKDB48mB07duBwOAB4++23effddyktLSU1NZX09HTKy8v56KOPcLlcfn3v3r17s337dgBKS0vZ\nunXrBV8zZMgQrrzySv7whz/4XterVy+sViu7du3i2LFjvjpNJhONjY307NmTsrIy8vPzAfjss89Y\ns2aNX7dFJNJppC4SYU6dOsWsWbN83w8ePJgHH3yQX//61/z0pz8lLi6O2NhYFi9eTFpaGj169GDK\nlCl0796de++9l/nz5zNhwgS/1TN58mTef/99pk2bRrdu3RgxYsQZI/qzuf/++7nhhhv47ne/y3XX\nXcedd97JzJkzGTZsGD/+8Y9ZuHAhf//73xk3bhw//OEPeeaZZ/j973/Pr3/9a+x2OwC//e1v/bYd\nItFAd2kTkXYpLi5m27ZtTJo0CY/Hw0033cT8+fNbHK8XkeDQSF1E2iUpKYm33nqLFStWYDKZGD9+\nvAJdJEQ0UhcREYkSWignIiISJRTqIiIiUUKhLiIiEiUU6iIiIlFCoS4iIhIlFOoiIiJR4v8HegYv\n+RXTZvUAAAAASUVORK5CYII=\n",
            "text/plain": [
              "<matplotlib.figure.Figure at 0x7f1de6cb8b70>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "-FzBtPBFZUY_",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "\"i guess we don't set learning rate anymore?\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "vULiUTDBCQue",
        "colab_type": "code",
        "outputId": "7e2e8ee8-3b0b-4b38-ae63-c425b5c1c7a4",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 136
        }
      },
      "cell_type": "code",
      "source": [
        "learn.fit_one_cycle(3)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 1:48:26 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>8.569375</th>\n",
              "    <th>8.106207</th>\n",
              "    <th>0.806758</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>7.396843</th>\n",
              "    <th>5.606319</th>\n",
              "    <th>0.627429</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>3</th>\n",
              "    <th>6.544768</th>\n",
              "    <th>5.240096</th>\n",
              "    <th>0.599823</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "jV51TvHREe8o",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "learn.save('whale-checkpoint')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "HkWSyEWkaLzX",
        "colab_type": "code",
        "outputId": "5f1a37b5-b25a-4b78-8f80-8b7560996626",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "cell_type": "code",
      "source": [
        "learn.unfreeze()\n",
        "learn.lr_range(slice(1e-6,1e-2))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([1.e-06, 1.e-04, 1.e-02])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 21
        }
      ]
    },
    {
      "metadata": {
        "id": "OTVFjkQyOOpO",
        "colab_type": "code",
        "outputId": "5553a2bc-6cbe-4dcb-bbd5-0b5cc37c01a5",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:27 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>5.183479</th>\n",
              "    <th>4.649187</th>\n",
              "    <th>0.571776</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>5.004416</th>\n",
              "    <th>4.516306</th>\n",
              "    <th>0.563825</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "AfF_I-qBfGvS",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "At this point -- I have been deleting the output because they are being flooded with `Exception Ignored` output to the point its lagging the tab.  Loss has also been dropping"
      ]
    },
    {
      "metadata": {
        "id": "F70RTv_fcutp",
        "colab_type": "code",
        "outputId": "bd1b11a7-7789-4232-ad92-53c13bd70c0a",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:24 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>4.765259</th>\n",
              "    <th>4.383919</th>\n",
              "    <th>0.563604</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>4.595328</th>\n",
              "    <th>4.252269</th>\n",
              "    <th>0.556316</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "U625715ic1y7",
        "colab_type": "code",
        "outputId": "79da44ba-5cfc-41c8-ee95-82547ba72af6",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:29 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>4.383812</th>\n",
              "    <th>4.195163</th>\n",
              "    <th>0.563825</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>4.214738</th>\n",
              "    <th>4.024258</th>\n",
              "    <th>0.548807</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "7IEGNCfkyvSX",
        "colab_type": "code",
        "outputId": "4f4b4228-c383-4df8-b430-9f0ce4af0f80",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_range(slice(1e-7,1e-2))\n",
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:06 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>4.001510</th>\n",
              "    <th>3.980694</th>\n",
              "    <th>0.548145</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>3.840297</th>\n",
              "    <th>3.819719</th>\n",
              "    <th>0.538869</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "4dv-Q--rwcNP",
        "colab_type": "code",
        "outputId": "55303531-7395-4a48-c1a1-a23845ab5118",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_range(slice(1e-8,1e-3))\n",
        "learn.fit_one_cycle(2)\n"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:18 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>3.637510</th>\n",
              "    <th>3.831148</th>\n",
              "    <th>0.553224</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>3.493265</th>\n",
              "    <th>3.668150</th>\n",
              "    <th>0.529152</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "QKvt7r_Qwnu3",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "learn.save('whaleoverfit1')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "IL8HL0fzkkLH",
        "colab_type": "code",
        "outputId": "ba061ff4-1b7d-4263-f342-1af2aff2141e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_range(slice(1e-9,1e-4))\n",
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 23:46 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>3.301567</th>\n",
              "    <th>3.728911</th>\n",
              "    <th>0.541519</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>3.167062</th>\n",
              "    <th>3.525004</th>\n",
              "    <th>0.523189</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "8_SvZy_qmhPK",
        "colab_type": "code",
        "outputId": "8a34b506-87d0-4b2e-d30e-9555f7a384f0",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_range(slice(1e-9,1e-4))\n",
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:53 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>3.005531</th>\n",
              "    <th>3.622818</th>\n",
              "    <th>0.528048</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>2.900909</th>\n",
              "    <th>3.449982</th>\n",
              "    <th>0.512588</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "o_mjUFNRHwHL",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "learn.save('whaleoverfit2')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "eSEaNzeINg_4",
        "colab_type": "code",
        "outputId": "1f007d5b-d391-4113-d296-6faa31a0069f",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_range(slice(1e-9,1e-4))\n",
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:56 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>2.750777</th>\n",
              "    <th>3.605768</th>\n",
              "    <th>0.539973</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>2.638514</th>\n",
              "    <th>3.381904</th>\n",
              "    <th>0.507288</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "-6k_dB8xNjvj",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "learn.save('whaleoverfit3')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "UKcpFJEQTYKz",
        "colab_type": "code",
        "outputId": "9a20d539-a0f4-41d6-f470-e4f761a3d9d3",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_range(slice(1e-9,1e-4))\n",
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:58 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>2.488919</th>\n",
              "    <th>3.567703</th>\n",
              "    <th>0.533348</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>2.404579</th>\n",
              "    <th>3.367573</th>\n",
              "    <th>0.508613</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "pWUIL69Md5pN",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "learn.save('whaleoverfit4')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "_NAajJ3CTbJW",
        "colab_type": "code",
        "outputId": "d14be9eb-7efc-4eae-d55a-f962b7e0753e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 115
        }
      },
      "cell_type": "code",
      "source": [
        "learn.lr_range(slice(1e-9,1e-3))\n",
        "learn.fit_one_cycle(2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "Total time: 24:57 <p><table style='width:300px; margin-bottom:10px'>\n",
              "  <tr>\n",
              "    <th>epoch</th>\n",
              "    <th>train_loss</th>\n",
              "    <th>valid_loss</th>\n",
              "    <th>error_rate</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>1</th>\n",
              "    <th>2.281792</th>\n",
              "    <th>3.468150</th>\n",
              "    <th>0.524072</th>\n",
              "  </tr>\n",
              "  <tr>\n",
              "    <th>2</th>\n",
              "    <th>2.218921</th>\n",
              "    <th>3.355711</th>\n",
              "    <th>0.506405</th>\n",
              "  </tr>\n",
              "</table>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "metadata": {
        "id": "VgG9IwHec--I",
        "colab_type": "code",
        "outputId": "12b56f90-be4c-4954-8979-a5865828866f",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 167
        }
      },
      "cell_type": "code",
      "source": [
        "data.export()"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "error",
          "ename": "NameError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-1-b82570d4156b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexport\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;31mNameError\u001b[0m: name 'data' is not defined"
          ]
        }
      ]
    },
    {
      "metadata": {
        "id": "9-X6kIhnLw1R",
        "colab_type": "code",
        "outputId": "88310827-6ad4-420c-abc8-8817eb4b11aa",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 72
        }
      },
      "cell_type": "code",
      "source": [
        "empty_data = ImageDataBunch.load_empty(BASE)\n",
        "learn = create_cnn(empty_data, models.resnet34)\n",
        "learn = learn.load('whaleoverfit3')"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Downloading: \"https://download.pytorch.org/models/resnet34-333f7ec4.pth\" to /root/.torch/models/resnet34-333f7ec4.pth\n",
            "100%|██████████| 87306240/87306240 [00:02<00:00, 29634446.31it/s]\n"
          ],
          "name": "stderr"
        }
      ]
    },
    {
      "metadata": {
        "id": "1LT7sfWZVsYA",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "!ls \"{BASE}/test\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "xe5-vokpuGoY",
        "colab_type": "code",
        "outputId": "8d7bc035-8af4-40c4-9ec1-b48bd06950ae",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 86
        }
      },
      "cell_type": "code",
      "source": [
        "learn.predict(open_image(f\"{BASE}/test/0aa98293e.jpg\"))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(Category new_whale,\n",
              " tensor(0),\n",
              " tensor([2.2085e-01, 1.3035e-06, 5.9053e-05,  ..., 3.3789e-05, 2.0548e-05,\n",
              "         7.6159e-07]))"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 10
        }
      ]
    },
    {
      "metadata": {
        "id": "sQCpW3hhuZi6",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "\n",
        "cat, tensor, probs = learn.predict(open_image(f\"{BASE}/test/d042ac24f.jpg\"))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "eixVxIswAyut",
        "colab_type": "code",
        "outputId": "991e40a1-2ca6-437b-82d3-1537ede875b8",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 52
        }
      },
      "cell_type": "code",
      "source": [
        "probs"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([9.6946e-01, 9.5974e-07, 3.4940e-05,  ..., 3.6891e-07, 4.5883e-06,\n",
              "        1.4004e-07])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 13
        }
      ]
    },
    {
      "metadata": {
        "id": "2gCU9K_JCNTv",
        "colab_type": "code",
        "outputId": "f142e037-1f90-4d5e-9ac9-d43c986c8939",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "cell_type": "code",
      "source": [
        "probs.shape"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([4528])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 14
        }
      ]
    },
    {
      "metadata": {
        "id": "JuVfrjTL-0aD",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "learn"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "xaPtRFph--AH",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}